package com.frontop.terminal.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.frontop.terminal.constant.CommonNumBerCodConst;
import com.frontop.terminal.constant.InterfaceConst;
import com.frontop.terminal.downloader.DownloadCenter;
import com.frontop.terminal.downloader.MultipleThreadDownloadTask;
import com.frontop.terminal.entity.File;
import com.frontop.terminal.entity.Message;
import com.frontop.terminal.entity.Program;
import com.frontop.terminal.entity.TerminalConfig;
import com.frontop.terminal.enums.HeaderEnum;
import com.frontop.terminal.model.bo.TerminalResourceBO;
import com.frontop.terminal.model.vo.RestResult;
import com.frontop.terminal.service.ICommandSerivce;
import com.frontop.terminal.util.ReadDataUtil;
import com.frontop.terminal.util.SystemMonitoringUtil;
import com.frontop.terminal.util.WriteDataUtil;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p>
 * 发布互动程序资源
 * </p>
 *
 * @author Frontop
 * @since :2022-06-28
 **/
@Slf4j
public class ProcedurePublishResourceServiceImpl implements ICommandSerivce {

    /**
     * 执行业务
     *
     * @param message 消息对象
     * @return T
     */
    @SuppressWarnings({"ConstantConditions"})
    @Override
    public RestResult executeWork(Message message) {

        TerminalResourceBO resourceBO = JSON.parseObject(message.getCommand(), TerminalResourceBO.class);

        if (ObjectUtil.isNotNull(resourceBO)) {

            //如果本地存在记录则修改 有时候会没同步删除
            Map<String, Program> programMap = ReadDataUtil.getProgramListMap();
            List<Program> list;
            if (ObjectUtil.isNotNull(programMap) && programMap.containsKey(resourceBO.getId())) {
                Program program = programMap.get(resourceBO.getId());
                program.setName(resourceBO.getResourceName());
                program.setFileId(resourceBO.getResourceId());
                program.setLocation(resourceBO.getResourceLocation());
                program.setSource(resourceBO.getResourceSource() == 1 ? 0 : 1);

                list = new ArrayList<>(programMap.values());
            } else {
                Program program = new Program();
                program.setId(resourceBO.getId());
                program.setName(resourceBO.getResourceName());
                program.setFileId(resourceBO.getResourceId());
                program.setLocation(resourceBO.getResourceLocation());
                program.setSource(resourceBO.getResourceSource() == 1 ? 0 : 1);

                list = ReadDataUtil.getProgramList();
                list.add(program);
            }

            //资源需要下载或者重新下载
            AtomicBoolean isNeedDownload = new AtomicBoolean(false);
            //true会通知中控更新状态，本地导入的资源会触发,中控发布在秒传成功触发
            boolean isDownloadIng = false;

            //如果是中控发布的资源需要下载文件
            if (resourceBO.getResourceSource().equals(CommonNumBerCodConst.ON)) {
                //取出本地文件下载记录
                Map<Long, File> fileMap = ReadDataUtil.getFileMap();
                if (ObjectUtil.isNotNull(fileMap) && fileMap.containsKey(resourceBO.getResourceId())) {
                    //本地已经下载过该文件，检测文件是否存在
                    File file = fileMap.get(resourceBO.getResourceId());
                    //下载完成
                    if (file.getDownloadStatus().equals(CommonNumBerCodConst.TWO)) {
                        //文件真实存在,结束流程保存
                        if (FileUtil.exist(file.getLocations())) {
                            list.forEach(entity -> {
                                if (entity.getId().equals(resourceBO.getId())) {

                                    //压缩包ZIP那解压后赋值
                                    String zipSuffix = "zip";

                                    //不是压缩文件直接赋值地址
                                    if (!FileUtil.getSuffix(file.getLocations()).equalsIgnoreCase(zipSuffix)) {
                                        //资源真实存在
                                        if (FileUtil.exist(file.getLocations())) {
                                            entity.setLocation(file.getLocations());
                                            log.info("[发布互动程序]秒传成功");
                                        } else {
                                            //资源不存在，重新下载资源
                                            isNeedDownload.set(true);
                                        }

                                    } else {
                                        log.info("检测到互动程序是压缩包格式,开始解压文件...");

                                        //解压文件
                                        java.io.File zipFile = null;
                                        try {
                                            zipFile = ZipUtil.unzip(file.getLocations(), CharsetUtil.CHARSET_GBK);
                                        } catch (Exception e) {
                                            log.error("解压文件失败");
                                        }

                                        String exeSuffix = "exe";
                                        //查找程序入口
                                        String exePath = DownloadCenter.getExeFile(zipFile.listFiles(), exeSuffix);

                                        if (!StrUtil.isEmpty(exePath)) {
                                            entity.setLocation(exePath);
                                        }
                                    }

                                }

                            });
                        } else {
                            isDownloadIng = true;
                            //加入下载任务
                            download(resourceBO, file);
                        }
                    } else {
                        //资源不存在，重新下载资源
                        isNeedDownload.set(true);
                    }
                } else {
                    //资源不存在，下载资源
                    isNeedDownload.set(true);
                }

                //资源需要下载
                if (isNeedDownload.get()) {
                    //请求中控获取File对象信息
                    String url = ReadDataUtil.getTerminalConfig().getServerAddress() + InterfaceConst.GET_FILE_LIST;
                    //请求文件详情列表
                    HttpResponse httpResponse = HttpRequest.get(url)
                            //设置连接超时和响应超时时间
                            .timeout(10000)
                            .header(HeaderEnum.TERMINAL_TOKEN.getKey(), ReadDataUtil.getTerminalConfig().getAuthorizationCode())
                            .form("ids", new ArrayList<>(Collections.singleton(resourceBO.getResourceId())))
                            .executeAsync();

                    if (!httpResponse.isOk()) {
                        log.warn("[发布互动程序]终端代理尝试下载互动程序资源过程中获取Fiel资源失败");
                        return RestResult.failed("[发布互动程序]终端代理尝试下载互动程序资源过程中获取Fiel资源失败");
                    }

                    List<File> fileList = JSON.parseArray(httpResponse.body(), File.class);
                    File file = fileList.get(0);

                    if (ObjectUtil.isNull(file)) {
                        log.warn("[发布互动程序]服务器返回File列表数据异常");
                        return RestResult.failed("[发布互动程序]服务器返回File列表数据异常");
                    }

                    isDownloadIng = true;
                    //下载
                    download(resourceBO, file);
                }
            }

            //保存
            WriteDataUtil.write(list, ReadDataUtil.PROGRAM_LIST_CODING);

            //通知中控发布成功
            String mac = SystemMonitoringUtil.getMacAddress();
            TerminalConfig terminalConfig = ReadDataUtil.getTerminalConfig();

            //只有在不下载资源情况才会进入
            if (ObjectUtil.isNotNull(terminalConfig) && !isDownloadIng) {
                String url = terminalConfig.getServerAddress() + InterfaceConst.DOWNLOAD_RESOURCE_SUCCESS;
                HttpRequest.post(url)
                        .header(HeaderEnum.TERMINAL_TOKEN.getKey(), ReadDataUtil.getTerminalConfig().getAuthorizationCode())
                        .form("mac", mac)
                        .form("id", resourceBO.getId())
                        .executeAsync();
            }

            return RestResult.success();
        }
        return RestResult.failed("[发布互动程序]资源返回数据异常");
    }

    @SuppressWarnings("ConstantConditions")
    private void download(TerminalResourceBO resourceBO, File file) {
        String url = ReadDataUtil.getTerminalConfig().getServerAddress()
                + InterfaceConst.TERMINAL_AGENT_RESOURCE_PART_DOWNLOAD + resourceBO.getResourceId();
        //获取当前日期 格式2021-7-23
        String currentDate = LocalDate.now() + FileUtil.FILE_SEPARATOR;
        String localPath = ReadDataUtil.getTerminalConfig().getResourceAddress() + currentDate;
        //如果当前日期文件夹不存在就创建
        if (!FileUtil.exist(localPath)) {
            FileUtil.mkdir(localPath);
        }
        //获取本地存储资源具体位置
        localPath += file.getName();

        //需保存File记录，不然无法记录文件下载状态
        List<File> fileList = ReadDataUtil.getFile();
        fileList.add(file);
        WriteDataUtil.write(fileList, ReadDataUtil.FILE_LIST_CODING);

        //加入下载任务
        DownloadCenter.setExecutorService(new MultipleThreadDownloadTask(url, new java.io.File(localPath), file.getId(), resourceBO.getResourceType()));
    }
}
